use std::fmt;
use serialize::{Encodable, Encoder, Decodable, Decoder};
-use util::profile;
-use util::graph::{Nodes, Edges};
-
-use core::{
- Dependency,
- PackageId,
- Registry,
- SourceId,
-};
-
use semver;
-use util::{CargoResult, Graph, human, internal};
+use core::{Dependency, PackageId, Registry, SourceId, PackageIdSpec};
+use util::graph::{Nodes, Edges};
+use util::profile;
+use util::{CargoResult, Graph, human, internal, ChainError};
#[deriving(PartialEq, Eq)]
pub struct Resolve {
pub fn deps(&self, pkg: &PackageId) -> Option<Edges<PackageId>> {
self.graph.edges(pkg)
}
+
+ pub fn query(&self, spec: &str) -> CargoResult<&PackageId> {
+ let spec = try!(PackageIdSpec::parse(spec).chain_error(|| {
+ human(format!("invalid package id specification: `{}`", spec))
+ }));
+ let mut ids = self.iter().filter(|p| spec.matches(*p));
+ let ret = match ids.next() {
+ Some(id) => id,
+ None => return Err(human(format!("package id specification `{}` \
+ matched no packages", spec))),
+ };
+ match ids.next() {
+ Some(other) => {
+ let mut msg = format!("Ambiguous package id specification: \
+ `{}`\nMatching packages:\n {}\n {}",
+ spec, ret, other);
+ for id in ids {
+ msg = format!("{}\n {}", msg, id);
+ }
+ Err(human(msg))
+ }
+ None => Ok(ret)
+ }
+ }
}
impl fmt::Show for Resolve {
let sources = match to_update {
Some(name) => {
let mut to_avoid = HashSet::new();
- for dep in resolve.iter().filter(|d| d.get_name() == name.as_slice()) {
- if aggressive {
- fill_with_deps(&resolve, dep, &mut to_avoid);
- } else {
- to_avoid.insert(dep);
- }
+ let dep = try!(resolve.query(name.as_slice()));
+ fill_with_deps(&resolve, dep, &mut to_avoid);
+ if aggressive {
+ fill_with_deps(&resolve, dep, &mut to_avoid);
+ } else {
+ to_avoid.insert(dep);
}
resolve.iter().filter(|pkgid| !to_avoid.contains(pkgid))
.map(|pkgid| pkgid.get_source_id().clone()).collect()